#include "Charge.h"

GPIO_TypeDef* CHARGE_PORT[CHARGEnPIN] = {CHARGE_STATUS_PORT,CHARGE_LEVEL_PORT};
const uint16_t CHARGE_PIN[CHARGEnPIN] = {CHARGE_STATUS_PIN,CHARGE_LEVEL_PIN};
const uint32_t CHARGE_CLK[CHARGEnPIN] = {CHARGE_STATUS_CLK,CHARGE_LEVEL_CLK};


/* Private define ------------------------------------------------------------*/
#define ADC1_DR_Address    ((uint32_t)0x4001244C)

/* Private variables ---------------------------------------------------------*/
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
volatile uint16_t ADCConvertedValue;
volatile uint16_t BatterryLevel[4] = {0,0,0,0};	

void ChargeInitController(){
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_ADCCLKConfig(RCC_PCLK2_Div4); 
  	/* Enable peripheral clocks ------------------------------------------------*/
  	/* Enable DMA1 clock */
  	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

	RCC_APB2PeriphClockCmd(CHARGE_STATUS_CLK, ENABLE);


	/* Configure the CHARGE_STATUS_PIN */
	GPIO_InitStructure.GPIO_Pin = CHARGE_STATUS_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_Init(CHARGE_PORT[CHARGE_STATUS], &GPIO_InitStructure);

	
	/* Enable ADC1 and GPIOC clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);


	/* Configure PA.7 (ADC Channel12) as analog input -------------------------*/
	GPIO_InitStructure.GPIO_Pin = CHARGE_LEVEL_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(CHARGE_PORT[CHARGE_LEVEL], &GPIO_InitStructure);

	/* DMA1 channel1 configuration ----------------------------------------------*/
	DMA_DeInit(DMA1_Channel1);
	DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	DMA_InitStructure.DMA_BufferSize = 1;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);

	/* Enable DMA1 channel1 */
	DMA_Cmd(DMA1_Channel1, ENABLE);

	/* ADC1 configuration ------------------------------------------------------*/
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);

	/* ADC1 regular channel12 configuration */ 
	ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 1, ADC_SampleTime_55Cycles5);

	/* Enable ADC1 DMA */
	ADC_DMACmd(ADC1, ENABLE);

	/* Enable ADC1 */
	ADC_Cmd(ADC1, ENABLE);

	/* Enable ADC1 reset calibaration register */   
	ADC_ResetCalibration(ADC1);
	/* Check the end of ADC1 reset calibration register */
	while(ADC_GetResetCalibrationStatus(ADC1));

	/* Start ADC1 calibaration */
	ADC_StartCalibration(ADC1);
	/* Check the end of ADC1 calibration */
	while(ADC_GetCalibrationStatus(ADC1));
	 
	/* Start ADC1 Software Conversion */ 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

void ReadBatterryLevel(){
	BatterryLevel[3]  = BatterryLevel[2];
	BatterryLevel[2]  = BatterryLevel[1];
	BatterryLevel[1] = ADCConvertedValue;
	if ((BatterryLevel[3] == BatterryLevel[2]) && (BatterryLevel[2] == BatterryLevel[1])){
		BatterryLevel[0]  = BatterryLevel[1];
	}
}

uint16_t GetBatterryLevel(){
	return (uint16_t)BatterryLevel[0];
}
